#include "SD_INIT.h"
#include "cJSON.h"
#include "esp_event.h"
#include "esp_https_server.h"
#include "esp_log.h"
#include "esp_vfs.h"
#include "esp_vfs_fat.h"
#include "esp_vfs_semihost.h"
#include "esp_wifi.h"
#include "lwip/err.h"
#include "nvs_flash.h"
#include "sdkconfig.h"
#include "sdmmc_cmd.h"
#include <esp_event.h>
#include <esp_log.h>
#include <esp_system.h>
#include <esp_wifi.h>
#include <nvs_flash.h>
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/unistd.h>

#include <fcntl.h>    // for open
#include <unistd.h>   // for close, read, write

#include "cJSON.h"
#include "driver/gpio.h"
#include "esp_netif.h"

#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
#include "esp_log.h"
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include <stdio.h>
#include <string.h>

#include <dirent.h>


static const char* TAG = "SD";

static esp_err_t s_example_write_file(const char* path, char* data)
{
    ESP_LOGI(TAG, "Opening file %s", path);
    FILE* f = fopen(path, "w");

    if (f == NULL)
    {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return ESP_FAIL;
    }
    fprintf(f, data);
    fclose(f);
    ESP_LOGI(TAG, "File written");

    return ESP_OK;
}

static esp_err_t s_example_read_file(const char* path)
{
    ESP_LOGI(TAG, "Reading file %s", path);
    FILE* f = fopen(path, "r");
    if (f == NULL)
    {
        ESP_LOGE(TAG, "Failed to open file for reading");
        return ESP_FAIL;
    }
    char line[EXAMPLE_MAX_CHAR_SIZE];
    fgets(line, sizeof(line), f);
    fclose(f);

    // strip newline
    char* pos = strchr(line, '\n');
    if (pos)
    {
        *pos = '\0';
    }
    ESP_LOGI(TAG, "Read from file: '%s'", line);

    return ESP_OK;
}

// 遍历目录的递归函数
// list_directory(MOUNT_POINT, 0);
void list_directory(const char* base_path, int depth)
{
    DIR* dir = opendir(base_path);   // 打开目录
    if (!dir)
    {
        ESP_LOGE(TAG, "Failed to open directory: %s", base_path);
        return;
    }

    struct dirent* entry;
    while ((entry = readdir(dir)) != NULL)
    {
        // 打印缩进用于显示层级结构
        for (int i = 0; i < depth; i++)
        {
            printf("  ");
        }

        if (entry->d_type == DT_DIR)
        {
            // 这是一个子目录
            printf("[DIR] %s\n", entry->d_name);
            if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
            {
                // 构建子目录的路径
                char sub_dir_path[512];
                snprintf(sub_dir_path, sizeof(sub_dir_path), "%s/%s", base_path, entry->d_name);
                // 递归调用
                list_directory(sub_dir_path, depth + 1);
            }
        }
        else if (entry->d_type == DT_REG)
        {
            // 这是一个文件
            printf("[FILE] %s\n", entry->d_name);
        }
    }
    closedir(dir);   // 关闭目录
}

void SD_TEST()
{
    esp_err_t  ret;
    const char data1[] = "/sdcard/web_image/index.html";
    // FILE* f      = fopen(data, "r");

    // if (f == NULL)
    // {
    //     ESP_LOGE(TAG, "Failed to open file for writing");

    // }
    // printf("open %s OK\r\n",data);
    // fclose(f);

    const char* file_hello = MOUNT_POINT "/hello.txt";
    char        data[EXAMPLE_MAX_CHAR_SIZE];
    snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Hello", "123456");
    ret = s_example_write_file(file_hello, data);
    if (ret != ESP_OK)
    {
        return;
    }
     const char* file_hello2 = MOUNT_POINT"/web_image/index.html";
    const char* file_hello1 = MOUNT_POINT "/index.html";
    // s_example_read_file(file_hello1);

    // int fd = open(file_hello2, O_RDONLY, 0);

    // printf(" filepath %s\r\n ", file_hello1);


    // if (fd == -1)
    // {
    //     ESP_LOGE(TAG, "Failed to open file : %s", file_hello2);
    //     return;
    // }

    // ESP_LOGI(TAG, " close file : %s", file_hello2);
    // close(fd);
}
void SD_Init()
{
    // SD初始化代码
    printf("SD init \r\n");

    esp_err_t                        ret;
    esp_vfs_fat_sdmmc_mount_config_t mount_config = {

        .format_if_mount_failed = false,
        // EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .max_files            = 5,
        .allocation_unit_size = 8 * 1024 * sizeof(uint8_t),
    };

    sdmmc_card_t* card;
    const char    mount_point[] = MOUNT_POINT;
    ESP_LOGI(TAG, "Initializing SD card");

    ESP_LOGI(TAG, "Using SPI peripheral");

    sdmmc_host_t host = SDSPI_HOST_DEFAULT();

    spi_bus_config_t bus_cfg = {
        .mosi_io_num     = 11,   // MOSI
        .miso_io_num     = 13,   // MISO
        .sclk_io_num     = 12,   // CLK
        .quadwp_io_num   = -1,
        .quadhd_io_num   = -1,
        .max_transfer_sz = 4000,
    };

    ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_DMA);
    if (ret != ESP_OK)
    {
        ESP_LOGE(TAG, "Failed to initialize bus.");
        return;
    }

    sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
    slot_config.gpio_cs               = 2;   // CS
    slot_config.host_id               = host.slot;

    ESP_LOGI(TAG, "Mounting filesystem");
    ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);

    if (ret != ESP_OK)
    {
        if (ret == ESP_FAIL)
        {
            ESP_LOGE(TAG,
                     "Failed to mount filesystem. "
                     "If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig "
                     "option.");
        }
        else
        {
            ESP_LOGE(TAG,
                     "Failed to initialize the card (%s). "
                     "Make sure SD card lines have pull-up resistors in place.",
                     esp_err_to_name(ret));
        }
        return;
    }

    ESP_LOGI(TAG, "Filesystem mounted");

    // Card has been initialized, print its properties
    sdmmc_card_print_info(stdout, card);
    list_directory(MOUNT_POINT, 4);
    SD_TEST();
    return;

    // const char* file_hello = MOUNT_POINT "/hello.txt";
    // char        data[EXAMPLE_MAX_CHAR_SIZE];
    // snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Hello", card->cid.name);
    // ret = s_example_write_file(file_hello, data);
    // if (ret != ESP_OK)
    // {
    //     return;
    // }

    // const char* file_foo = MOUNT_POINT "/foo.txt";

    // // Check if destination file exists before renaming
    // struct stat st;
    // if (stat(file_foo, &st) == 0)
    // {
    //     // Delete it if it exists
    //     unlink(file_foo);
    // }


    // // Rename original file
    // ESP_LOGI(TAG, "Renaming file %s to %s", file_hello, file_foo);
    // if (rename(file_hello, file_foo) != 0)
    // {
    //     ESP_LOGE(TAG, "Rename failed");
    //     return;
    // }

    // ret = s_example_read_file(file_foo);
    // if (ret != ESP_OK)
    // {
    //     return;
    // }

    // const char* file_nihao = MOUNT_POINT "/nihao.txt";
    // memset(data, 0, EXAMPLE_MAX_CHAR_SIZE);
    // snprintf(data, EXAMPLE_MAX_CHAR_SIZE, "%s %s!\n", "Nihao", card->cid.name);
    // ret = s_example_write_file(file_nihao, data);
    // if (ret != ESP_OK)
    // {
    //     return;
    // }

    // // Open file for reading
    // ret = s_example_read_file(file_nihao);
    // if (ret != ESP_OK)
    // {
    //     return;
    // }

    // // All done, unmount partition and disable SPI peripheral
    // esp_vfs_fat_sdcard_unmount(mount_point, card);
    // ESP_LOGI(TAG, "Card unmounted");

    // // deinitialize the bus after all devices are removed
    // spi_bus_free(host.slot);
    // printf("holle word\r\n");
    // // Deinitialize the power control driver if it was used
}
